package com.googlecode.cswish.util.crosssite;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.googlecode.cswish.model.CrossSiteModel;
import com.googlecode.cswish.struts.ContextHolder;
import com.googlecode.cswish.struts.hibernate.ISite;
import com.googlecode.cswish.struts.spring.Executor;

public class CrossSiteArrayList<E> extends ArrayList<E> implements CrossSiteModel<List<E>> {

	private static final long serialVersionUID = -4790718760396492440L;
	
	private Map<String, List<E>> siteListMapping = new ConcurrentHashMap<String, List<E>>();
	
	private Collection<E> initValue;
	
	private Executor<List<E>, Object> factory;
	
	public CrossSiteArrayList() {
	}
	
	public CrossSiteArrayList(Collection<E> initValue) {
		this.initValue = initValue;
	}
	
	public CrossSiteArrayList(List<E> initValue, Executor<List<E>, Object> factory) {
		this.initValue = initValue;
		this.factory = factory;
	}
	
	private List<E> getSiteList() {
		String siteName = ContextHolder.get().getSiteName();
		if (siteName == null) {
			siteName = ISite.DEFAULT_NAME;
		}
		List<E> siteList = siteListMapping.get(siteName);
		if (siteList == null) {
			synchronized (siteListMapping) {
				siteList = siteListMapping.get(siteName);
				if (siteList == null) {
					if (factory == null) {
						if (initValue == null) {
							siteList = new ArrayList<E>();
						} else {
							siteList = new ArrayList<E>(initValue);
						}
					} else {
						siteList = factory.execute(null);
						if (initValue != null) {
							siteList.addAll(initValue);
						}
					}
					siteListMapping.put(siteName, siteList);
				}
			}
		}
		return siteList;
	}
	
	public int size() {
		return getSiteList().size();
	}

	public boolean isEmpty() {
		return getSiteList().isEmpty();
	}

	public boolean contains(Object o) {
		return getSiteList().contains(o);
	}

	public Iterator<E> iterator() {
		return getSiteList().iterator();
	}

	public Object[] toArray() {
		return getSiteList().toArray();
	}

	public <T> T[] toArray(T[] a) {
		return getSiteList().toArray(a);
	}

	public boolean add(E e) {
		return getSiteList().add(e);
	}

	public boolean remove(Object o) {
		return getSiteList().remove(o);
	}

	public boolean containsAll(Collection<?> c) {
		return getSiteList().containsAll(c);
	}

	public boolean addAll(Collection<? extends E> c) {
		return getSiteList().addAll(c);
	}

	public boolean addAll(int index, Collection<? extends E> c) {
		return getSiteList().addAll(index, c);
	}

	public boolean removeAll(Collection<?> c) {
		return getSiteList().removeAll(c);
	}

	public boolean retainAll(Collection<?> c) {
		return getSiteList().retainAll(c);
	}

	public void clear() {
		getSiteList().clear();
	}

	public boolean equals(Object o) {
		return getSiteList().equals(o);
	}

	public int hashCode() {
		return getSiteList().hashCode();
	}

	public E get(int index) {
		return getSiteList().get(index);
	}

	public E set(int index, E element) {
		return getSiteList().set(index, element);
	}

	public void add(int index, E element) {
		getSiteList().add(index, element);
	}

	public E remove(int index) {
		return getSiteList().remove(index);
	}

	public int indexOf(Object o) {
		return getSiteList().indexOf(o);
	}

	public int lastIndexOf(Object o) {
		return getSiteList().lastIndexOf(o);
	}

	public ListIterator<E> listIterator() {
		return getSiteList().listIterator();
	}

	public ListIterator<E> listIterator(int index) {
		return getSiteList().listIterator(index);
	}

	public List<E> subList(int fromIndex, int toIndex) {
		return getSiteList().subList(fromIndex, toIndex);
	}

	@Override
	public void active(String site) {
		// TODO:
	}

	@Override
	public void passive(String site) {
		// TODO
	}

	@Override
	public void destroy(String site) {
		siteListMapping.remove(site);
	}

	@Override
	public List<E> getModelBySite(String site) {
		return siteListMapping.get(site);
	}
}